package com.tang.model.state.examination;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.StateMachineContext;
import org.springframework.statemachine.StateMachinePersist;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.persist.DefaultStateMachinePersister;
import org.springframework.statemachine.support.DefaultStateMachineContext;

import java.util.EnumSet;

/**
 * Created by Tom.
 */
@ComponentScan("com.tang.model.state.examination")
@Configuration
@EnableStateMachine(name = "stateMachine")
public class ExamineOrderConfig extends StateMachineConfigurerAdapter<ExamineStatusEnum, ExamineStatusActionEnum> {
    /**
     * 配置状态
     *
     * @param states
     * @throws Exception
     */
    public void configure(StateMachineStateConfigurer<ExamineStatusEnum, ExamineStatusActionEnum> states) throws Exception {
        states.withStates()
                .initial(ExamineStatusEnum.NO_APPOINTMENT)
                .states(EnumSet.allOf(ExamineStatusEnum.class));
    }

    @Override
    public void configure(StateMachineTransitionConfigurer<ExamineStatusEnum, ExamineStatusActionEnum> transitions) throws Exception {
        /**
         * 配置状态转换事件关系
         *
         * @param transitions
         * @throws Exception
         */
        transitions
                .withExternal().source(ExamineStatusEnum.NO_APPOINTMENT).target(ExamineStatusEnum.APPOINTMENT).event(ExamineStatusActionEnum.RESERVE)
                .and()
                .withExternal().source(ExamineStatusEnum.APPOINTMENT).target(ExamineStatusEnum.UNFILL_INFORMATION).event(ExamineStatusActionEnum.TAKE_NUMBER)
                .and()
                .withExternal().source(ExamineStatusEnum.UNFILL_INFORMATION).target(ExamineStatusEnum.PENDING_PAYMENT).event(ExamineStatusActionEnum.ENTRY_INFORMATION)
                .and()
                .withExternal().source(ExamineStatusEnum.PENDING_PAYMENT).target(ExamineStatusEnum.UNCHECKED).event(ExamineStatusActionEnum.PAYMENT)
                .and()
                .withExternal().source(ExamineStatusEnum.UNCHECKED).target(ExamineStatusEnum.PENDING_REPORT).event(ExamineStatusActionEnum.EXAMINE)
                .and()
                .withExternal().source(ExamineStatusEnum.PENDING_REPORT).target(ExamineStatusEnum.COMPLETED).event(ExamineStatusActionEnum.PUBLISHED);
    }

    /**
     * 持久化配置
     * 实际使用中，可以配合redis等，进行持久化操作
     *
     * @return
     */
    @Bean
    public DefaultStateMachinePersister persister() {
        return new DefaultStateMachinePersister<>(new StateMachinePersist<Object, Object, ExamineOrder>() {
            @Override
            public void write(StateMachineContext<Object, Object> context, ExamineOrder order) throws Exception {
                //此处并没有进行持久化操作
            }

            @Override
            public StateMachineContext<Object, Object> read(ExamineOrder order) throws Exception {
                //此处直接获取order中的状态，其实并没有进行持久化读取操作
                return new DefaultStateMachineContext(order.getStatus(), null, null, null);
            }
        });
    }
}
